/*
 * MovementHandler.cpp
 *
 *  Created on: 28/10/2013
 *      Author: fernando
 */

#include "MovementHandler.h"
#include "Confite.h"
#include "Barrita.h"
#include "EstrellaDorada.h"
#include "SDL/SDL_mixer.h"
#include "../logica/Posicion.h"
#include <iostream>
#include <math.h>
#include <cstdlib>
#include <vector>

using std::cout;
using std::endl;
using std::vector;

const int MAXMOV = 64;
const int HORIZONTAL = 0;
const int VERTICAL = 1;
extern const int SIZEEXTRA;
extern const int SIZECELDA;


int getDiferencia(int a, int b){
	return (a-b);
}

MovementHandler::MovementHandler(TableroSDL* tableroAUsar) {
	limiteAlcanzado = false;
	mouseApretado = false;
	xOrigen = 0;
	yOrigen = 0;
	xActual = 0;
	yActual = 0;
	tablero = tableroAUsar;
	direccion = -1;
}

MovementHandler::~MovementHandler() {
}

void MovementHandler::ubicarMouse(unsigned int x, unsigned int y){
	int diferenciaX, diferenciaY;
	if(!limiteAlcanzado && x > 0 && y > 0 && x < tablero->getAncho()-SIZEEXTRA){
		xActual = x;
		yActual = y;
	}
	if (mouseApretado){
		diferenciaX = std::abs(getDiferencia(x,xOrigen));
		diferenciaY = std::abs(getDiferencia(y,yOrigen));
		if (direccion == -1){
			if (diferenciaX > diferenciaY){
				direccion = 0;
			}else{
				direccion = 1;
			}
		}
		if((diferenciaX >= MAXMOV) || (diferenciaY >= MAXMOV)){
			limiteAlcanzado = true;
		}
		moverGolosina();
	}
}

void MovementHandler::moverGolosina(){
	if (direccion == 0){
		golosinaOrigen->setPosicion(tablero->getPosCorner(xActual), tablero->getPosCorner(yOrigen));
	}else{
		golosinaOrigen->setPosicion(tablero->getPosCorner(xOrigen), tablero->getPosCorner(yActual));
	}
	golosinaOrigen->dibujar(tablero->getScreen());
}

void MovementHandler::pulsaGolosina(){
	xOrigen = xActual;
	yOrigen = yActual;
	if (!mouseApretado){
		golosinaOrigen = tablero->getGolosinaConPosicion(xActual, yActual);
		if (golosinaOrigen != NULL){
			mouseApretado = true;
		}
	}
}

int MovementHandler::soltarGolosina(){
	CeldaSDL *celdaOrigen, *celdaDestino;
	int counter = 1;
	int puntaje = 0;
	if (mouseApretado){
		celdaDestino = tablero->getCeldaFromPos(golosinaOrigen->getPosX(), golosinaOrigen->getPosY());
		celdaOrigen = tablero->getCeldaFromPos(xOrigen, yOrigen);
		Posicion p1(celdaOrigen->getPosY()/SIZECELDA, celdaOrigen->getPosX()/SIZECELDA);
		Posicion p2(celdaDestino->getPosY()/SIZECELDA, celdaDestino->getPosX()/SIZECELDA);
		if (celdaDestino->getEstado() && !celdaDestino->isVacia() && !(p1 == p2)){
			golosinaDestino = celdaDestino->getGolosina();
			golosinaDestino->setPosicion(celdaOrigen->getPosX(), celdaOrigen->getPosY());
			celdaOrigen->setGolosina(golosinaDestino);
			golosinaOrigen->setPosicion(celdaDestino->getPosX(), celdaDestino->getPosY());
			celdaDestino->setGolosina(golosinaOrigen);
			if(!partida->intercambiarGolosinas(p1, p2)){
				intercambiar(celdaOrigen->getNumero(), celdaDestino->getNumero());
			}else{
				do{
					partida->setMultiplicador(counter);
					eliminarYRellenarPosiciones();
					partida->limpiarVectores();
					tablero->dibujar();
					SDL_Delay(200);
					counter++;
				}while(partida->verificarMatchs());
			}
		}else{
			golosinaOrigen->setPosicion(celdaOrigen->getPosX(), celdaOrigen->getPosY());
			cout << "Color logica: " << (partida->getCelda(p1.getX(), p1.getY()))->getColorGolosina() << endl;
			cout << "Color interfaz: " << golosinaOrigen->getColor() << endl;
		}
		puntaje = partida->getPuntosJugada();
		partida->vaciarPuntosJugada();
		mouseApretado = false;
		limiteAlcanzado = false;
		direccion = -1;
		golosinaOrigen = NULL;
		golosinaDestino = NULL;
	}
	return puntaje;
}

void MovementHandler::destruirGolosina(CeldaSDL* celda){
	Mix_Chunk *explode = NULL;
	explode = Mix_LoadWAV("trunk/Sonidos/missile.wav");
//	vector<SDL_Surface*> imagenes = celda->getGolosina()->getImagenes();
//  for (unsigned int i = (imagenes.size() - 2); i == 0 ; i--){
		//SDL_FreeSurface(imagenes.at(i+1));
		//tablero->dibujar();
		//imagenes.pop_back();
		//SDL_Delay(50);
//  }
//	Mix_PauseMusic();
	Mix_PlayChannel(-1, explode, 0);
	celda->vaciar();
	if (((celda->getNumero())%(tablero->getNumeroFilas())) > 0){
		bajarGolosina(celda->getNumero() - 1);
	}
//	Mix_ResumeMusic();
	//Mix_FreeChunk(explode);
}

void MovementHandler::destruirGolosinas(vector<int> celdas){
	CeldaSDL* celda;
	for (vector<int>::iterator It = celdas.begin(); It != celdas.end(); ++It){
		celda = tablero->getCelda(*It);
		destruirGolosina(celda);
	}
}


void MovementHandler::bajarGolosina(unsigned int nCelda){
	unsigned int nCeldaAbajo = nCelda+1;
	CeldaSDL* celda;
	CeldaSDL* celdaAbajo;
	Golosina* golosina;
	celdaAbajo = tablero->getCelda(nCeldaAbajo);
	celda = tablero->getCelda(nCelda);
	if (nCeldaAbajo%tablero->getNumeroFilas() != 0){
		if(!celda->isVacia()){
			while (!celdaAbajo->getEstado() && nCeldaAbajo%tablero->getNumeroFilas() != 0){
				nCeldaAbajo++;
				celdaAbajo = tablero->getCelda(nCeldaAbajo);
			}
			if (celdaAbajo->isVacia()){
				golosina = celda->getGolosina();
				golosina->setPosicion(celdaAbajo->getPosX(), celdaAbajo->getPosY());
				celdaAbajo->setGolosina(golosina);
				celda->vaciar();
				if (nCelda != 0){
					bajarGolosina(nCelda-1);
				}else if((nCelda + 1 ) != (tablero->getNumeroColumnas()*tablero->getNumeroFilas())){
					bajarGolosina(nCeldaAbajo);
				}

			}
		}else if(nCelda > 0){
			nCelda -= 1;
			bajarGolosina(nCelda);
		}
	}
}

void MovementHandler::reponerGolosina(Golosina* golosina, unsigned int columna){
	CeldaSDL* celda;
	unsigned int nCel = (columna)*(tablero->getNumeroFilas());
	celda = tablero->getCelda(nCel);
	golosina->setPosicion(celda->getPosX(), celda->getPosY());
	celda->setGolosina(golosina);
//	bajarGolosina(celda->getNumero());
}

void MovementHandler::reponerGolosinas(vector<Golosina*> golosinas, unsigned int columna){
	for (vector<Golosina*>::iterator It = golosinas.begin(); It != golosinas.end(); ++It){
		reponerGolosina(*It, columna);
	}
}



void MovementHandler::intercambiar(unsigned int nCelda1, unsigned int nCelda2){
	CeldaSDL* celdaOrigen = tablero->getCelda(nCelda1);
	CeldaSDL* celdaDestino = tablero->getCelda(nCelda2);
	Golosina* golosinaDestino = celdaDestino->getGolosina();
	Golosina* golosinaOrigen = celdaOrigen->getGolosina();
	golosinaDestino->setPosicion(celdaOrigen->getPosX(), celdaOrigen->getPosY());
	celdaOrigen->setGolosina(golosinaDestino);
	golosinaOrigen->setPosicion(celdaDestino->getPosX(), celdaDestino->getPosY());
	celdaDestino->setGolosina(golosinaOrigen);
}

void MovementHandler::setPartida(Partida* p){
	partida = p;
}

unsigned int MovementHandler::getCeldaFromPos(unsigned int nFil, unsigned int nCol){
	return nCol* partida->getFilas() + nFil;
}

void MovementHandler::eliminarYRellenarPosiciones(){
	CeldaSDL* celdaVista;
	int contador = 0;
	Pieza* piezaActual;
	vector<Posicion> posEspeciales = partida->getPosicionesEspeciales();
	vector<Pieza*> especiales = partida->getEspeciales();
	for (vector<Posicion>::iterator It = posEspeciales.begin(); It != posEspeciales.end(); ++It){
		celdaVista = tablero->getCelda(getCeldaFromPos((*It).getX(),(*It).getY()));
		celdaVista->vaciar();
		piezaActual = especiales.at(contador);
		celdaVista->setGolosina(piezaActual->getVista((*It).getY()*SIZECELDA, (*It).getX()*SIZECELDA));
		contador++;
	}
	contador = 0;
	vector<Posicion> posiciones = partida->getPosicionesAEliminar();
	vector<Pieza*> piezas = partida->getARellenar();
	for (vector<Posicion>::iterator It = posiciones.begin(); It != posiciones.end(); ++It){
		celdaVista = tablero->getCelda(getCeldaFromPos((*It).getX(),(*It).getY()));
		destruirGolosina(celdaVista);
		piezaActual = piezas.at(contador);
		reponerGolosina(piezaActual->getVista((*It).getY()*SIZECELDA, 0),(*It).getY());
		contador++;
	}
}
